package com.ymatou.utils;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.GenericMultipleBarcodeReader;
import com.google.zxing.multi.MultipleBarcodeReader;
import com.google.zxing.qrcode.QRCodeReader;
import com.ymatou.iapi.better.parameter.FindApplicationEnvByAppAndEnvBean;
import com.ymatou.iapi.better.parameter.ListApplicationsBean;
import com.ymatou.iapi.better.service.FindApplicationEnvByAppAndEnvCall;
import com.ymatou.iapi.better.service.ListApplicationsCall;
import com.ymatou.iapi.fileupload.service.UploadCall;
import com.ymatou.utils.constant.AreaCode;
import com.ymatou.utils.constant.ChineseName;
import com.ymatou.utils.constant.PhoneNum;
import com.ymt.base.GetFileCall;
import com.ymt.core.tool.Logger;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.client.ClientProtocolException;
import parsii.eval.Parser;
import parsii.eval.Scope;
import parsii.tokenizer.ParseException;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestDataManager {

    //	Byte-order mark Description
//	EF BB BF UTF-8
    public static final byte[] UTF8BOM={(byte)0xef,(byte)0xbb,(byte)0xbf};
    //	FF FE UTF-16 aka UCS-2, little endian
    public static final byte[] UTF16LEBOM={(byte)0xff,(byte)0xfe};
    //	FE FF UTF-16 aka UCS-2, big endian
    public static final byte[] UTF16BEBOM={(byte)0xff,(byte)0xff};
    //	00 00 FF FE UTF-32 aka UCS-4, little endian.
    public static final byte[] UTF32lEBOM={(byte)0x00,(byte)0x00,(byte)0xff,(byte)0xfe};
    //	00 00 FE FF UTF-32 aka UCS-4, big-endian.
    public static final byte[] UTF32BEBOM={(byte)0x00,(byte)0x00,(byte)0xfe,(byte)0xff};

    private static ArrayList<String> filelist = new ArrayList<>();

    // 种子值
    private static long seed = System.currentTimeMillis();
    // 随机数生成器
    private static Random random = new Random(seed);
    /**
     * parsii计算表达式 <br/> 举例 exp="0.003*x+35"; xname="x"; xvalue=1000d; return 38<br/>
     * @param exp 表达式
     * @param xname 变量名
     * @param xvalue 变量值
     * @return 计算结果
     * @throws ParseException
     */
    public static Double Expression(String exp,String xname,Double xvalue) throws ParseException {
        Scope scope = new Scope();
        scope.getVariable(xname).setValue(xvalue);
        parsii.eval.Expression expr = Parser.parse(exp, scope);
        return expr.evaluate();
    }
    /**
     * parsii计算表达式 -多元表达式<br/>
     * 举例 exp="0.003*x+35-y";var.put("x", 1000d);var.put("y", 10d); return 28<br/>
     * @param exp 表达式
     * @param var key 变量名 value 变量值
     * @return 计算结果
     * @throws ParseException
     */
    public static Double Expression(String exp,Map<String,Double> var) throws ParseException {
        Scope scope = new Scope();
        var.entrySet().forEach(entry->{
            scope.getVariable(entry.getKey()).setValue(entry.getValue());
        });
        parsii.eval.Expression expr = Parser.parse(exp, scope);
        return expr.evaluate();
    }
    /**
     * 执行yum update 解决网络问题？
     *
     * @param ip
     * @param uname
     * @param pwd
     * @throws InterruptedException
     */
    public static void RunYumUpdate(String ip, String uname, String pwd)
            throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        executor.execute(() -> {
            RemoteShellExecutor2 rse = new RemoteShellExecutor2(ip, uname, pwd);
            try {
                rse.login();
                rse.exec("yum update");
                rse.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        Thread.sleep(3000);
        executor.shutdownNow();
    }

    /**
     * 转换utfString
     *
     * @param utfString
     * @return
     */
    public static String convertUnicode(String utfString) {
        StringBuilder sb = new StringBuilder();
        int i = -1;
        int pos = 0;

        while ((i = utfString.indexOf("\\u", pos)) != -1) {
            sb.append(utfString.substring(pos, i));
            if (i + 5 < utfString.length()) {
                pos = i + 6;
                sb.append((char) Integer.parseInt(
                        utfString.substring(i + 2, i + 6), 16));
            }
        }
        sb.append(utfString.substring(pos, utfString.length()));
        return sb.toString();
    }

    /**
     * 获取移动手机号
     *
     * @return 移动手机号
     */
    public static String getCommPhoneNum() {
        StringBuffer pnum = new StringBuffer();
        Random r = new Random();
        int code = PhoneNum.SH.get(r.nextInt(PhoneNum.SH.size()));
        pnum.append(code);
        for (int i = 0; i < 4; i++) {
            int n = r.nextInt(10);
            pnum.append(n);
        }
        return pnum.toString();
    }

    /**
     * 随机生成数字串
     *
     * @param size
     *            多少位
     * @return
     */
    public static String getRandomNum(int size) {
        StringBuffer pnum = new StringBuffer();
        Random r = new Random();
        pnum.append(r.nextInt(8) + 1);
        for (int i = 0; i < size - 1; i++) {
            int n = r.nextInt(10);
            pnum.append(n);
        }
        return pnum.toString();
    }

    /**
     * 获取随机email
     *
     * @return
     */
    public static String getEmail() {
        String mail = TestDataManager.randomStr(new Random().nextInt(5) + 8);
        String[] mails = { "@126.com", "@163.com", "@qq.com", "@baidu.com",
                "@sina.com", "@sohu.com", "@gmail.com", "@foxmail.com",
                "@yahoo.com", "@taobao.com" };
        int i = new Random().nextInt(mails.length);
        mail += mails[i];

        return mail;
    }

    /**
     * 获取随机手机号
     *
     * @return 手机号
     */
    public static String getPhoneNum() {
        StringBuffer pnum = new StringBuffer();
        Random r = new Random();
        pnum.append("13");
        for (int i = 0; i < 9; i++) {
            int n = r.nextInt(10);
            pnum.append(n);
        }
        return pnum.toString();
    }

    /**
     * @param begin
     *            手机号前两位
     * @return
     */
    public static String getPhoneNum(String begin) {
        StringBuffer pnum = new StringBuffer();
        Random r = new Random();
        pnum.append(begin);
        for (int i = 0; i < 9; i++) {
            int n = r.nextInt(10);
            pnum.append(n);
        }
        return pnum.toString();
    }

    /**
     * 获取一串唯一的clientPaymentId 本质为获取 添加同步锁后 sleep nanos 1 get System.nanoTime
     *
     * @return 不重复的nanoTime戳
     */
    public static synchronized String getClientpaymentId() {
        try {
            Thread.sleep(0, 1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return String.valueOf(System.nanoTime());

    }

    /**
     * 生成随机身份证号，可指定男女
     *
     * @param fyear
     *            最小年龄
     * @param yearLen
     *            随机波动年龄
     * @param sex
     *            单数男 双数女
     * @return 身份证
     */
    public static String getCardId(int fyear, int yearLen, int sex) {
        String c1 = getCardId(fyear, yearLen).substring(0, 16) + sex % 10;
        String v = getVerify(c1);
        c1 += v;
        return c1;
    }

    /**
     * 生成随机身份证号
     *
     * @param fyear
     *            最小年龄
     * @param yearLen
     *            随机波动年龄
     * @return 身份证
     */
    public static String getCardId(int fyear, int yearLen) {
        String ret = "";
        FileWriter fw = null;
        try {
            Random random = new Random();

            String areaCode = AreaCode.AC
                    .get(random.nextInt(AreaCode.AC.size()));

            int year = Calendar.getInstance().get(Calendar.YEAR) - fyear
                    - random.nextInt(yearLen);
            int month = random.nextInt(11);
            if (month == 0)
                month = 12;
            int day = 0;
            while (true) {
                day = random.nextInt(31);
                if (!((day == 0 || (month == 4 || month == 6 || month == 9 || month == 11)
                        && day > 30) || (month == 2 && (((year) % 4 > 0 && day > 28) || day > 29)))) {
                    break;
                }
            }
            String birthday = String.valueOf(year * 10000 + month * 100 + day);
            String randomCode = String.valueOf(1000 + random.nextInt(999))
                    .substring(1);
            String verify = getVerify(areaCode + birthday + randomCode);
            ret = areaCode + birthday + randomCode + verify;
            return ret;

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 根据17位身份证号获取验证码
     *
     * @param cardId
     *            17位身份证号
     * @return 验证码平日
     */
    public static String getVerify(String cardId) {
        String[] ValCodeArr = { "1", "0", "x", "9", "8", "7", "6", "5", "4",
                "3", "2" };
        String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7",
                "9", "10", "5", "8", "4", "2" };
        int TotalmulAiWi = 0;
        for (int i = 0; i < 17; i++) {
            TotalmulAiWi = TotalmulAiWi
                    + Integer.parseInt(String.valueOf(cardId.charAt(i)))
                    * Integer.parseInt(Wi[i]);
        }
        int modValue = TotalmulAiWi % 11;
        String strVerifyCode = ValCodeArr[modValue];

        return strVerifyCode;
    }

    /**
     * 获取中文名
     *
     * @return 中文名
     */
    public static String getChineseName() {
        Random random = new Random();
        String xing = "";
        String ming = "";

        int i = random.nextInt(ChineseName.Xing.size());
        xing = ChineseName.Xing.get(i);
        i = random.nextInt(ChineseName.Ming.size());
        String temp_m = ChineseName.Ming.get(i);
        int j = random.nextInt(temp_m.length());
        ming = temp_m.substring(j, j + 1);
        return xing + ming;
    }
    public static String getUTF8Base64(String text){
        return java.util.Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
    }
    /**
     * 把文件转换为base64编码串
     *
     * @param filepath
     * @return
     * @throws Exception
     */
    public static String getBase64(String filepath) throws Exception {

        byte[] buf = null;
        try {
            InputStream fs = new FileInputStream(filepath);
            buf = new byte[fs.available()];
            fs.read(buf);
            fs.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Class<?> clazz = Class
                .forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
        Method mainMethod = clazz.getMethod("encode", byte[].class);
        mainMethod.setAccessible(true);
        Object retObj = mainMethod.invoke(null, new Object[] { buf });
        return (String) retObj;

    }

    /**
     * 拼接byte
     *
     * @param data1
     * @param data2
     * @return
     */
    public static byte[] addBytes(byte[] data1, byte[] data2) {
        if (data1 == null) {
            return data2;
        }
        if (data2 == null) {
            return data1;
        }
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;

    }
    /**
     * 获取文件md5
     * @param path
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String getFileMD5(String path) throws FileNotFoundException, IOException {
        return DigestUtils.md5Hex(new FileInputStream(path));
    }
    /**
     * 含有unicode 的字符串转一般字符串
     * @param unicodeStr 混有 Unicode 的字符串
     * @return
     */
    public static String unicodeStr2String(String unicodeStr) {
        int length = unicodeStr.length();
        int count = 0;
        //正则匹配条件，可匹配“\\u”1到4位，一般是4位可直接使用 String regex = "\\\\u[a-f0-9A-F]{4}";
        String regex = "\\\\u[a-f0-9A-F]{1,4}";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(unicodeStr);
        StringBuffer sb = new StringBuffer();

        while(matcher.find()) {
            String oldChar = matcher.group();//原本的Unicode字符
            String newChar = unicode2String(oldChar);//转换为普通字符
            // int index = unicodeStr.indexOf(oldChar);
            // 在遇见重复出现的unicode代码的时候会造成从源字符串获取非unicode编码字符的时候截取索引越界等
            int index = matcher.start();

            sb.append(unicodeStr.substring(count, index));//添加前面不是unicode的字符
            sb.append(newChar);//添加转换后的字符
            count = index+oldChar.length();//统计下标移动的位置
        }
        sb.append(unicodeStr.substring(count, length));//添加末尾不是Unicode的字符
        return sb.toString();
    }
    /**
     * unicode 转字符串
     * @param unicode 全为 Unicode 的字符串
     * @return
     */
    public static String unicode2String(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");

        for (int i = 1; i < hex.length; i++) {
            // 转换出每一个代码点
            int data = Integer.parseInt(hex[i], 16);
            // 追加成string
            string.append((char) data);
        }

        return string.toString();
    }
    /**
     * 获取md5串
     *
     * @param source
     *            源数据
     * @return source对应的md5
     */
    public static String getMD5(byte[] source) {
        String s = null;
        char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
                'e', 'f' };
        try {
            java.security.MessageDigest md = java.security.MessageDigest
                    .getInstance("MD5");
            md.update(source);
            byte tmp[] = md.digest(); // MD5 的计算结果是一个 128 位的长整数，
            // 用字节表示就是 16 个字节
            char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符，
            // 所以表示成 16 进制需要 32 个字符
            int k = 0; // 表示转换结果中对应的字符位置
            for (int i = 0; i < 16; i++) { // 从第一个字节开始，对 MD5 的每一个字节
                // 转换成 16 进制字符的转换
                byte byte0 = tmp[i]; // 取第 i 个字节
                str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
                // >>>
                // 为逻辑右移，将符号位一起右移
                str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
            }
            s = new String(str); // 换后的结果转换为字符串

        } catch (Exception e) {
            e.printStackTrace();
        }
        return s;
    }

    /**
     * json串转换为Map
     *
     * @param strjson
     *            json字符串
     * @return Map<String, Object>
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> getMapFromJson(String strjson) {
        Map<String, Object> map = JSONObject.fromObject(strjson);
        return map;
    }

    /**
     * 判断char是否为中文
     *
     * @param c
     * @return
     */
    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
            return true;
        }
        return false;
    }

    /**
     * 判断string中是否有中文
     *
     * @param strName
     *            字符串
     * @return 是否有中文字符 有返回true
     */
    public static boolean hasChinese(String strName) {
        char[] ch = strName.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            if (isChinese(c)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 初始化数据 获取ArrayList<String[]> 读取文件 每行一个string[] 空格分割
     *
     * @param
     * fileName 文件名
     * @return ArrayList<String[]>
     */
    public static ArrayList<String[]> getData(String fileName) {
        ArrayList<String[]> as = new ArrayList<String[]>();
        RandomAccessFile readFile = null;
        try {
            File file = new File(fileName);
            if (file.exists()) {
                readFile = new RandomAccessFile(fileName, "r");
                String s = null;
                while ((s = readFile.readLine()) != null) {
                    s = new String(s.getBytes("iso8859-1"), "utf-8");
                    as.add(s.split(" "));
                }
                try {
                    readFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (as.size() == 0) {
            as.add(new String[0]);
        }
        return as;
    }

    /**
     * 初始化数据 获取ArrayList<String[]> 读取文件 每行一个string[] 空格分割
     *
     * @param fileName
     *            文件名
     * @param slipt
     *            分隔符
     * @return ArrayList<String[]>
     */
    public static ArrayList<String[]> getData(String fileName, String slipt) {
        ArrayList<String[]> as = new ArrayList<String[]>();
        RandomAccessFile readFile = null;
        try {
            File file = new File(fileName);
            if (file.exists()) {
                readFile = new RandomAccessFile(fileName, "r");
                String s = null;
                while ((s = readFile.readLine()) != null) {
                    s = new String(s.getBytes("iso8859-1"), "utf-8");
                    as.add(s.split(slipt));
                }
                try {
                    readFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (as.size() == 0) {
            as.add(new String[0]);
        }
        return as;
    }

    /**
     * 初始化数据 获取ArrayList<String[]> 读取文件 每行一个string
     *
     * @param fileName
     *            文件名
     * @return ArrayList<String>
     */
    public static ArrayList<String> getLines(String fileName) {
        ArrayList<String> as = new ArrayList<String>();
        RandomAccessFile readFile = null;
        try {
            File file = new File(fileName);
            if (file.exists()) {
                readFile = new RandomAccessFile(fileName, "r");
                String s = null;
                while ((s = readFile.readLine()) != null) {
                    s = new String(s.getBytes("iso8859-1"), "utf-8");
                    as.add(s);
                }
                try {
                    readFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (as.size() == 0) {
            as.add("");
        }
        return as;
    }

    /**
     * 初始化数据 获取ArrayList<String[]> 读取文件 每行一个string
     *
     * @param fileName
     *            文件名
     * @return ArrayList<String>
     */
    public static String getAllLines(String fileName) {
        StringBuffer as = new StringBuffer();
        RandomAccessFile readFile = null;
        try {
            File file = new File(fileName);
            if (file.exists()) {
                readFile = new RandomAccessFile(fileName, "r");
                String s = null;
                while ((s = readFile.readLine()) != null) {
                    s = new String(s.getBytes("iso8859-1"), "utf-8");
                    as.append(s);
                }
                try {
                    readFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (as.length() == 0) {
            as.append("");
        }
        return as.toString();
    }

    /**
     * 获取该目录下所有文件路径list
     *
     * @param filePath
     *            目录路径
     * @return 文件路径list
     */
    public static ArrayList<String> getFilelist(String filePath) {
        filelist = new ArrayList<String>();
        getFiles(filePath);
        return filelist;
    }

    /*
     * 通过递归得到某一路径下所有的目录及其文件
     */
    private static void getFiles(String filePath) {
        File root = new File(filePath);
        File[] files = root.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    /*
                     * 递归调用
                     */
                    getFiles(file.getAbsolutePath());
                    Logger.debug("显示" + filePath + "下所有子目录:"
                            + file.getAbsolutePath());
                } else {
                    filelist.add(file.getAbsolutePath());
                    // Logger.info("显示"+filePath+"下所有文件:"+file.getAbsolutePath());
                }
            }
        } else {
            Logger.debug("filePath not found files:" + filePath);
        }
    }

    /**
     * 随机返回0到1之间的实数 [0,1)
     *
     * @return double 随机数
     */
    public static double uniform() {
        return random.nextDouble();
    }

    /**
     * 随机返回0到N-1之间的整数 [0,N)
     *
     * @param N
     *            上限
     * @return int 随机数
     */
    public static int uniform(int N) {
        return random.nextInt(N);
    }

    /**
     * 随机返回0到1之间的实数 [0,1)
     *
     * @return double 随机数
     */
    public static double random() {
        return uniform();
    }

    /**
     * 随机返回a到b-1之间的整数 [a,b)
     *
     * @param a
     *            下限
     * @param b
     *            上限
     * @return int 随机数
     */
    public static int uniform(int a, int b) {
        return a + uniform(b - a);
    }

    /**
     * 随机返回a到b之间的实数
     *
     * @param a
     *            下限
     * @param b
     *            上限
     * @return double 随机数
     */
    public static double uniform(double a, double b) {
        return a + uniform() * (b - a);
    }

    /**
     * 返回随机字符串，同时包含数字、大小写字母
     *
     * @param len
     *            字符串长度，不能小于1
     * @return String 随机字符串
     */
    public static String randomStr(int len) {
        if (len < 1) {
            throw new IllegalArgumentException("字符串长度不能小于1");
        }
        // 数组，用于存放随机字符
        char[] chArr = new char[len];
        // 为了保证必须包含数字、大小写字母
        chArr[0] = (char) ('0' + uniform(0, 10));
        chArr[1] = (char) ('A' + uniform(0, 26));
        chArr[2] = (char) ('a' + uniform(0, 26));

        char[] codes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
                'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
                'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
                'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
                'x', 'y', 'z' };
        // charArr[3..len-1]随机生成codes中的字符
        for (int i = 3; i < len; i++) {
            chArr[i] = codes[uniform(0, codes.length)];
        }

        // 将数组chArr随机排序
        for (int i = 0; i < len; i++) {
            int r = i + uniform(len - i);
            char temp = chArr[i];
            chArr[i] = chArr[r];
            chArr[r] = temp;
        }

        return new String(chArr);
    }

    /**
     * 获取一串随机HexString
     *
     * @param num
     *
     * @return fffffffffffcc33a
     */
    public static String getRandomNumToHex(Integer num) {
        Random random = new Random();
        long max = 9;
        long min = 1;
        for (int i = 0; i < num; i++) {
            max = max * 10;
            min = min * 10;
        }
        long s = random.nextLong() % (max - min + 1) + min;
        String hexs = Long.toHexString(s);
        if (hexs.length() > num) {
            hexs = hexs.substring((hexs.length() - num.intValue()));
        }
        return hexs;
    }

    /**
     * 生成N位随机数的数字
     *
     * @param num
     *            数字长度
     * @return
     */
    public static int getRandomIntNum(int num) {
        Random rand = new Random();
        int n = 1;
        for (int i = 0; i < num; i++) {
            n = n * 10;
        }
        return (int) rand.nextInt(n);

    }

    /**
     * 生成一串uuid<br>
     *
     * @return
     */
    public static UUID getRandomUUID() {
        return UUID.randomUUID();
    }

    /**
     * 把一串字符串追加写入一个文件
     *
     * @param path
     *            文件路径
     * @param filebody
     *            文件内容
     *
     */
    public synchronized static void appendFileToLine(String path,
                                                     String filebody) {
        if (path == null || path.length() <= 1) {
            Logger.debug("没有指定文件路径");
            return;
        }
        File f1 = new File(path);
        FileOutputStream fo1 = null;
        try {
            if (!f1.exists()) {
                f1.createNewFile();
            }
            fo1 = new FileOutputStream(f1, true);
            new PrintStream(fo1).println(filebody);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    /**
     * 写入指定BOM头格式文件
     * @param path 文件路径
     * @param lines 每一行一条记录
     * @param encoding 目前支持 StandardCharsets.UTF_16LE StandardCharsets.UTF_16BE StandardCharsets.UTF_8
     * @throws IOException
     */
    public static void writeToFile(String path, List<String> lines, Charset encoding)
            throws IOException {
        if (path == null || path.length() <= 1) {
            Logger.debug("没有指定文件路径");
            return;
        }
        File f = new File(path);
        if (!f.exists()) {
            f.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(f);
        OutputStreamWriter writer = new OutputStreamWriter(fos, encoding.toString());
        if(encoding.equals(StandardCharsets.US_ASCII)){
            writer = new OutputStreamWriter(fos,"gb2312");
        }
        BufferedWriter bw = new BufferedWriter(writer);
        if(encoding.equals(StandardCharsets.UTF_8)) {
            bw.write(new String(TestDataManager.UTF8BOM,StandardCharsets.UTF_8));
        }else if(encoding.equals(StandardCharsets.UTF_16LE)) {
            bw.write(new String(TestDataManager.UTF16LEBOM,StandardCharsets.UTF_16LE));
        }
        else if(encoding.equals(StandardCharsets.UTF_16BE)) {
            bw.write(new String(TestDataManager.UTF16BEBOM,StandardCharsets.UTF_16BE));
        }

        bw.flush();
        writer.flush();
        fos.flush();
        for (String s : lines) {
            bw.write(s);
            bw.newLine();
        }
        bw.flush();
        writer.flush();
        fos.flush();
        bw.close();
        writer.close();
        fos.close();
    }
    public synchronized static void appendFileToLine(String path,
                                                     String filebody,String encoding) {
        if (path == null || path.length() <= 1) {
            Logger.debug("没有指定文件路径");
            return;
        }
        File f1 = new File(path);
        FileOutputStream fo1 = null;
        try {
            if (!f1.exists()) {
                f1.createNewFile();
            }
            fo1 = new FileOutputStream(f1, true);
            new PrintStream(fo1,true,encoding).println(new String (filebody.getBytes(),encoding));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    /**
     * 获取匹配正则表达式结果的结果列
     *
     * @param rts
     *            源数据
     * @param regEx
     *            正则表达式
     * @return 结果数组
     */
    public static List<String> getRegexList(String rts, String regEx) {
        List<String> finds = new ArrayList<String>();
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(rts);
        while (m.find()) {
            finds.add(m.group());
        }
        return finds;
    }

    /**
     * list 去除重复值
     *
     * @param list
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static List removeDuplicateWithOrder(List list) {
        Set set = new HashSet();
        List newList = new ArrayList();
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Object element = iter.next();
            if (set.add(element)) {
                newList.add(element);
            }
        }
        return newList;
    }

    /**
     * 删除文件
     *
     * @param path
     *            要删除的文件
     * @return 是否删除
     */
    public static boolean removeFile(String path) {
        File f1 = new File(path);
        if (!f1.exists()) {
            return false;
        }
        return f1.delete();
    }
    /**
     * 移动文件
     * @param srcFile
     * @param destPath 目录
     * @return
     */
    public static boolean MoveFile(String srcFile, String destPath) {
        // File (or directory) to be moved
        File file = new File(srcFile);
        // Destination directory
        File dir = new File(destPath);
        dir.mkdirs();
        // Move file to new directory
        boolean success = file.renameTo(new File(dir, file.getName()));
        return success;
    }
    /**
     * 文件copy
     * @param sourceFilePath
     * @param targetFilePath
     */
    public static void FileCopy(String sourceFilePath, String targetFilePath) throws IOException {
        File sourceFile = new File(sourceFilePath);
        File targetFile = new File(targetFilePath);
        targetFile.mkdirs();
        // 新建文件输入流并对它进行缓冲
        FileInputStream input = new FileInputStream(sourceFile);
        BufferedInputStream inBuff = new BufferedInputStream(input);
        // 新建文件输出流并对它进行缓冲
        FileOutputStream output = new FileOutputStream(targetFilePath+sourceFile.getName());
        BufferedOutputStream outBuff = new BufferedOutputStream(output);
        // 缓冲数组
        byte[] b = new byte[1024 * 5];
        int len;
        while ((len = inBuff.read(b)) != -1) {
            outBuff.write(b, 0, len);
        }
        // 刷新此缓冲的输出流
        outBuff.flush();
        // 关闭流
        inBuff.close();
        outBuff.close();
        output.close();
        input.close();
    }

    /**
     * 删除临时文件夹中的文件
     */
    public static void removeTempFile() {
        // 为防止批量误删，批量删除功能不做成通用方法
        ArrayList<String> list = getFilelist(System.getProperty("user.dir")
                + File.separator + "temp" + File.separator);
        for (String filename : list) {
            File f1 = new File(filename);
            f1.delete();
        }
    }

    /**
     * @return true---是Windows操作系统
     */
    public static boolean isWindowsOS() {
        boolean isWindowsOS = false;
        String osName = System.getProperty("os.name");
        if (osName.toLowerCase().indexOf("windows") > -1) {
            isWindowsOS = true;
        }
        return isWindowsOS;
    }

    /**
     * 修改本机dns
     *
     * @param ncname
     *            例如：本地连接
     * @param ip
     *            dns ip地址 172.16.110.240
     */
    public static void ChangeDns(String ncname, String ip) {
        BufferedReader br = null;
        try {
            Process p = Runtime.getRuntime().exec(
                    "netsh interface ip set dns \"" + ncname + "\" static "
                            + ip + " primary");
            br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null) {
                Logger.debug(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取本机ip地址
     *
     * @return ip
     * @throws UnknownHostException
     * @throws SocketException
     */
    public static String getLocalIp() throws UnknownHostException,
            SocketException {
        String host = null;
        NetworkInterface iface = null;

        for (Enumeration<NetworkInterface> ifaces = NetworkInterface
                .getNetworkInterfaces(); ifaces.hasMoreElements();) {
            iface = (NetworkInterface) ifaces.nextElement();
            InetAddress ia = null;
            for (Enumeration<InetAddress> ips = iface.getInetAddresses(); ips
                    .hasMoreElements();) {
                ia = (InetAddress) ips.nextElement();
                if (!ia.isLoopbackAddress() && (!ia.isLinkLocalAddress())
                        && (ia instanceof Inet4Address))
                    host = ia.getHostAddress();
            }
        }
        Logger.debug(host);
        return host;
    }

    /**
     * 获取一个随机的ip地址格式的String,其中第一个ip段大于173
     *
     * @return ip
     */
    public static String getRandomIp() {
        String ip = "";
        Random r = new Random();
        ip += (r.nextInt(50) + 173) + "." + r.nextInt(255) + "."
                + r.nextInt(255) + "." + r.nextInt(255);
        return ip;
    }
    /**
     * 获取一个ipv6
     * @return
     */
    public static String getRandomIpV6() {
        String ip =getRandomNumToHex(4).toUpperCase();
        for (int i = 0; i <7; i++) {
            ip+=":"+getRandomNumToHex(4).toUpperCase();
        }

        return ip;
    }
    /**
     * 下载一个文件
     *
     * @param url
     *            下载地址
     * @return 文件路径
     * @throws Exception
     */
    public static String DownloadFile(String url) throws Exception {
        GetFileCall gf = new GetFileCall(url);
        gf.callService();
        return gf.getFile();

    }

    /**
     * 判断一个文件是否是图片
     *
     * @param resFile
     *            文件
     * @return true or false
     */
    public static boolean isPic(File resFile) {
        boolean isPic = true;
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(resFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (bi == null) {
            isPic = false;
        }
        return isPic;
    }

    /**
     * 获取一个BufferedImage
     *
     * @param resFile
     *            文件
     * @return BufferedImage
     */
    public static BufferedImage getBufferedImage(File resFile) {
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(resFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bi;
    }

    /**
     * 比较一个BigDecimal 和 String 是否一致
     *
     * @param bd
     * @param num
     * @return
     */
    public static boolean equalsBigDecimal(BigDecimal bd, String num) {
        try {
            if (bd.compareTo(new BigDecimal(num)) == 0) {
                return true;
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    /**
     * 通过文件全路径获取Class <br>
     * 从com开始解析
     *
     * @param fname
     *            E:\testwork\Testing\source\YMTTest\src\com\ymt\testcase\api\
     *            address\Ts_AddAddress.java
     * @return like class com.ymt.testcase.api.address.Ts_AddAddress
     * @throws ClassNotFoundException
     */
    public static Class<?> getClassNameByFileName(String fname)
            throws Exception {
        // 这里需要优化 目的是找到bin目录 实际会找到域名中带有bin的地方
        int last = fname.lastIndexOf(".");
        if (fname.lastIndexOf("bin") == fname.indexOf("bin")) {
            fname = fname.substring(fname.indexOf("bin") + 4, last).replace(
                    File.separator, ".");
        } else {
            // 去头尾
            fname = fname.substring(fname.indexOf("bin") + 4, last);
            // 再去头
            fname = fname.substring(fname.indexOf("bin") + 4).replace(
                    File.separator, ".");
        }
        return Class.forName(fname);
    }

    /**
     * 根据域名获取IP地址
     *
     * @author chenjiazhu
     * @param name
     *            eg:www.sun.com
     * @return
     */
    public static String getServerIP(String name) {
        InetAddress address = null;
        try {
            address = InetAddress.getByName(name);
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("获取失败");
        }
        return address.getHostAddress().toString();
    }

    public static <T> boolean isListEqual(List<T> list1, List<T> list2) {
        for (T str : list2) {
            if (!list1.contains(str))
                return false;
        }
        for (T str : list1) {
            if (!list2.contains(str))
                return false;
        }
        return true;
    }

    /**
     * 将ip转换成long
     *
     * @param ip
     * @return
     */
    public static long converIpToLong(String ip) {
        String[] ipArray = ip.split("[.]");
        long result = (long) ((Math.pow(2, 24) * Integer.parseInt(ipArray[0])
                + Math.pow(2, 16) * Integer.parseInt(ipArray[1])
                + Math.pow(2, 8) * Integer.parseInt(ipArray[2]) + Math
                .pow(2, 0) * Integer.parseInt(ipArray[3])));
        return result;
    }

    /**
     * 获取域名ip
     *
     * @param domain
     * @return
     * @throws UnknownHostException
     */
    public static String getDnsIp(String domain) throws UnknownHostException {
        InetAddress[] ips = InetAddress.getAllByName(domain);
        if (ips.length >= 1) {
            return ips[0].getHostAddress();
        } else {
            return "";
        }

    }

    /**
     * 获取测试环境ip
     *
     * @param domain
     * @param env
     *            1=sit1
     * @return
     * @throws UnknownHostException
     */
    public static String getTestIp(String domain, Integer env) throws Exception {
        ListApplicationsCall list = new ListApplicationsCall();
        ListApplicationsBean listbean = new ListApplicationsBean();
        listbean.setDomain(domain);
        listbean.setPageindex(1);
        listbean.setPagesize(100);
        listbean.setDepartmentid("");
        listbean.setApplicationtypeid("");
        list.setData(false, listbean);
        list.callService();
        String id = list.getId();
        FindApplicationEnvByAppAndEnvBean fbean = new FindApplicationEnvByAppAndEnvBean();
        fbean.setApplicationid(Integer.valueOf(id));
        fbean.setEnvid(env);
        FindApplicationEnvByAppAndEnvCall fcall = new FindApplicationEnvByAppAndEnvCall();
        fcall.setData(false, fbean);
        fcall.callService();
        return fcall.getIp();
    }

    /**
     * 创建二维码图片
     *
     * @param content
     * @param path
     * @throws IOException
     * @throws WriterException
     */
    public static void CreateMatrixFile(String content, String path)
            throws IOException, WriterException {
        int width = 200; // 图像宽度
        int height = 200; // 图像高度
        String format = "png";// 图像类型
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵
        Path path2 = FileSystems.getDefault().getPath(path);
        MatrixToImageWriter.writeToPath(bitMatrix, format, path2);// 输出图像
    }
    /**
     * 创建图码
     * @param content
     * @param path
     * @param BarcodeFormat
     * @throws IOException
     * @throws WriterException
     */
    public static void CreateMatrixFile(String content, String path,BarcodeFormat BarcodeFormat)
            throws IOException, WriterException {
        int width = 200; // 图像宽度
        int height = 200; // 图像高度
        String format = "png";// 图像类型
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                BarcodeFormat, width, height, hints);// 生成矩阵
        Path path2 = FileSystems.getDefault().getPath(path);
        MatrixToImageWriter.writeToPath(bitMatrix, format, path2);// 输出图像
    }
    /**
     * 获取二维码信息
     *
     * @param filePath
     * @return
     * @throws Exception
     */
    public static String GetMatrixInfo(String filePath)
            throws Exception {
        BufferedImage image = ImageIO.read(new File(filePath));
//		return decodeQrCode(image);
        LuminanceSource source = new BufferedImageLuminanceSource(image);

        Binarizer binarizer = new HybridBinarizer(source);

        BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);

        Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();

        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        //优化精度
        hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
        //复杂模式，开启PURE_BARCODE模式
        hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
        hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
        Result result = new QRCodeReader().decode(binaryBitmap, hints);// 对图像进行解码
        ResultPoint[] rps = result.getResultPoints();
        for (int i = 0; i < rps.length; i++) {
            System.out.println("x:"+rps[i].getX()+":y:"+rps[i].getY());
        }
        return result.getText();
    }
    /**
     * https://github.com/zxing/zxing/blob/master/zxingorg/src/main/java/com/google/zxing/web/DecodeServlet.java
     * 解码
     * @param filePath
     * @return
     * @throws Exception
     */
    public static List<String> DecodeHint(String filePath) throws Exception {
        BufferedImage image = ImageIO.read(new File(filePath));
        Map HINTS = new EnumMap<>(DecodeHintType.class);
        HINTS.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
        HINTS.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
        Map HINTS_PURE = new EnumMap<>(HINTS);
        HINTS_PURE.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
        Collection<Result> results = new ArrayList<>(1);

        try {

            com.google.zxing.Reader reader = new MultiFormatReader();
            ReaderException savedException = null;
            try {
                // Look for multiple barcodes
                MultipleBarcodeReader multiReader = new GenericMultipleBarcodeReader(reader);
                Result[] theResults = multiReader.decodeMultiple(bitmap, HINTS);
                if (theResults != null) {
                    results.addAll(Arrays.asList(theResults));
                }
            } catch (ReaderException re) {
                savedException = re;
            }

            if (results.isEmpty()) {
                try {
                    // Look for pure barcode
                    Result theResult = reader.decode(bitmap, HINTS_PURE);
                    if (theResult != null) {
                        results.add(theResult);
                    }
                } catch (ReaderException re) {
                    savedException = re;
                }
            }

            if (results.isEmpty()) {
                try {
                    // Look for normal barcode in photo
                    Result theResult = reader.decode(bitmap, HINTS);
                    if (theResult != null) {
                        results.add(theResult);
                    }
                } catch (ReaderException re) {
                    savedException = re;
                }
            }

            if (results.isEmpty()) {
                try {
                    // Try again with other binarizer
                    BinaryBitmap hybridBitmap = new BinaryBitmap(new HybridBinarizer(source));
                    Result theResult = reader.decode(hybridBitmap, HINTS);
                    if (theResult != null) {
                        results.add(theResult);
                    }
                } catch (ReaderException re) {
                    savedException = re;
                }
            }


        } catch (RuntimeException re) {
        }
        List<String> qrresults=new ArrayList<>();
        for (Result result : results) {
            qrresults.add(result.getText());
        }
        return qrresults;
    }
//	public static String decodeQrCode(BufferedImage image) throws Exception
//	{
//	    // Convert the image to a binary bitmap source
//	    LuminanceSource source = new BufferedImageLuminanceSource(image);
//	    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
//
//	    // Decode the barcode
//	    QRCodeReader reader = new QRCodeReader();
//	    Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
//
//	    hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
//	    hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
//	    hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
//	    hints.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);
//	    Result result = null;
//	    try
//	    {
//	        result = reader.decode(bitmap,hints);
//	    }
//	    catch (NotFoundException | ChecksumException | FormatException e)
//	    {
//	        throw e;
//	    }
//	    return result == null ? null : result.getText();
//	}
    /**
     * 上传文件
     *
     * @param fpath
     *            路径
     * @return 图片路径
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String UploadFile(String fpath)
            throws ClientProtocolException, IOException {
        Logger.comment("开始上传文件");
        UploadCall uploadcall = new UploadCall();
        String turl = "";
        Logger.comment("添加上传文件:" + fpath);
        uploadcall.addPart("file", fpath);
        uploadcall.callService();
        return uploadcall.getFileUrl();
    }

    public static BigDecimal randomPrice(BigDecimal min, BigDecimal max) {

        return new BigDecimal(Math.random()).multiply(max.subtract(min))
                .add(min).setScale(2, BigDecimal.ROUND_HALF_UP);

    }
    /**
     *  检查文件里的站点名是否在better系统中
     * @param domainlistfile 文件名
     */
    public static void checkDomain(String domainlistfile) {
        getLines(domainlistfile).forEach(domain->{
            try {
                ListApplicationsCall list = new ListApplicationsCall();
                ListApplicationsBean listbean = new ListApplicationsBean();
                listbean.setDomain(domain.trim());
                listbean.setPageindex(1);
                listbean.setPagesize(100);
                listbean.setDepartmentid("");
                listbean.setApplicationtypeid("");
                list.setData(false, listbean);
                list.callService();
                String id = list.getId();
            } catch (Exception e) {
                appendFileToLine("nofound", domain);
                e.printStackTrace();
            }
        });
    }
    /*移除Map中值为空的键值对*/
    public static void removeNullEntry(Map map) {
        removeNullKey(map);
        removeNullValue(map);
    }
    /*移除键为空的键值对*/
    public static void removeNullKey(Map map) {
        Set set = map.keySet();
        for (Iterator iterator = set.iterator(); iterator.hasNext(); ) {
            Object obj = (Object) iterator.next();
            remove(obj, iterator);
        }
    }
    /*移除值为空的键值对*/
    public static void removeNullValue(Map map) {
        Set set = map.keySet();
        for (Iterator iterator = set.iterator(); iterator.hasNext(); ) {
            Object obj = (Object) iterator.next();
            Object value = (Object) map.get(obj);
            remove(value, iterator);
        }
    }

    private static void remove(Object obj, Iterator iterator) {
        if (obj instanceof String) {
            String str = (String) obj;
            if (str == null || str.trim().isEmpty()) {
                iterator.remove();
            }
        } else if (obj instanceof Collection) {
            Collection col = (Collection) obj;
            if (col == null || col.isEmpty()) {
                iterator.remove();
            }

        } else if (obj instanceof Map) {
            Map temp = (Map) obj;
            if (temp == null || temp.isEmpty()) {
                iterator.remove();
            }

        } else if (obj instanceof Object[]) {
            Object[] array = (Object[]) obj;
            if (array == null || array.length <= 0) {
                iterator.remove();
            }
        } else {
            if (obj == null) {
                iterator.remove();
            }
        }
    }
    public static void main(String[] args) throws Exception {
        double d=1.1d;
        System.out.println(d);
        System.out.println(new BigDecimal(Double.toString(1.1d)));


    }
}
